

#ifndef __WORKLOAD_H
#define __WORKLOAD_H

class WorkLoad
{
	HANDLE mutex;

	std::vector<IVideoDecoder*> work;
	const Settings &settings;
	const VideoFactory factory;

public:

	WorkLoad(const Settings &_settings) 
		:	settings(_settings),
			factory(_settings) {
		
		Initialise();
	}

	virtual ~WorkLoad() {

		CleanUp();
	}

	void DoSomeWork() {

		IVideoDecoder *vid = GetWork();

		if(vid) {
			if( vid->DecodeFrame() )
				ReturnWork( vid ); 
			else
				FinishedWork( vid );
		}
		else
			Sleep(1);
	}

private:

	IVideoDecoder *GetWork() {

		IVideoDecoder *vid = NULL;

		WaitForSingleObject(mutex, INFINITE);

		if(work.size())
		{

			std::vector<IVideoDecoder*>::iterator it = work.begin() + ( rand() % work.size() );

			vid = *it;

			work.erase( it );

		}
		
		ReleaseMutex( mutex );

		return vid;
	}

	void FinishedWork(IVideoDecoder *vid) {

		factory.KillVideo( vid );

		WaitForSingleObject(mutex, INFINITE);

		AddWork(1);
		
		ReleaseMutex( mutex );

	}

	void ReturnWork(IVideoDecoder *vid) {

		WaitForSingleObject(mutex, INFINITE);

		work.push_back( vid );
		
		ReleaseMutex( mutex );
	}

	void AddWork(int vids) {

		for(int i=0; i<vids; i++)
			work.push_back( factory.CreateVideo() );
	}

	void Initialise() {

		mutex = CreateMutex(NULL,false,NULL);

		AddWork( settings.ParallelVids() );
	}

	void CleanUp() {

		WaitForSingleObject(mutex, INFINITE);

		for(unsigned int i=0; i<work.size();i++)
			factory.KillVideo( work[i] );

		work.resize( 0 );

		CloseHandle( mutex );
	}
};

#endif /*** __WORKLOAD_H ***/

